use crate::core::{BuildConfiguration, BuildSettings, Project, ProjectType, Solution, SourceFile, CustomBuildRule};
use crate::parsers::Parser;
use crate::BuildMigrateError;
use crate::Result;
use crate::environment::EnvironmentResolver;
use crate::config::EnvironmentVariablesConfig;
use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use log::info;
use xml::reader::{EventReader, XmlEvent};

pub struct VsParser {
    /// 环境变量配置
    env_config: Option<EnvironmentVariablesConfig>,
}

impl Parser for VsParser {
    fn parse(&self, input_path: &Path) -> Result<Solution> {
        let extension = input_path.extension()
            .and_then(|s| s.to_str())
            .ok_or_else(|| BuildMigrateError::UnsupportedFormat("No file extension".to_string()))?;

        // 将输入路径规范化为绝对路径，避免相对路径和绝对路径混用的问题
        // 同时移除 Windows 的 \\?\ 前缀
        let input_canonical = input_path.canonicalize()
            .ok()
            .map(|p| Self::normalize_path(&p))
            .unwrap_or_else(|| {
                // 如果无法规范化（文件不存在等），尝试转换为绝对路径
                if input_path.is_absolute() {
                    input_path.to_path_buf()
                } else {
                    std::env::current_dir()
                        .map(|cwd| cwd.join(input_path))
                        .unwrap_or_else(|_| input_path.to_path_buf())
                }
            });

        match extension {
            "sln" => self.parse_solution(&input_canonical),
            "vcxproj" => {
                let project = self.parse_project(&input_canonical)?;
                let source_dir = input_canonical.parent()
                    .map(|p| p.to_path_buf())
                    .unwrap_or_else(|| {
                        std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
                    });
                let mut solution = Solution::with_source_directory(
                    input_canonical.file_stem()
                        .and_then(|s| s.to_str())
                        .unwrap_or("Unknown")
                        .to_string(),
                    source_dir
                );
                solution.projects.push(project);
                Ok(solution)
            }
            _ => Err(BuildMigrateError::UnsupportedFormat(format!("Unsupported extension: {}", extension))),
        }
    }

    fn supported_extensions(&self) -> &[&str] {
        &["sln", "vcxproj"]
    }
}

impl VsParser {
    pub fn new() -> Self {
        Self {
            env_config: None,
        }
    }

    pub fn with_env_config(env_config: EnvironmentVariablesConfig) -> Self {
        Self {
            env_config: Some(env_config),
        }
    }

    /// 移除 Windows 的扩展路径前缀 `\\?\`
    fn normalize_path(path: &Path) -> PathBuf {
        let path_str = path.to_string_lossy();
        let value = path_str.as_ref();

        if let Some(stripped) = value.strip_prefix(r"\\?\UNC\") {
            let mut prefixed = String::from(r"\\");
            prefixed.push_str(stripped);
            PathBuf::from(prefixed)
        } else if let Some(stripped) = value.strip_prefix(r"\??\UNC\") {
            let mut prefixed = String::from(r"\\");
            prefixed.push_str(stripped);
            PathBuf::from(prefixed)
        } else if value.starts_with(r"\\?\") {
            PathBuf::from(&value[4..])
        } else if value.starts_with(r"\??\") {
            PathBuf::from(&value[4..])
        } else {
            path.to_path_buf()
        }
    }

    fn parse_solution(&self, sln_path: &Path) -> Result<Solution> {
        let content = std::fs::read_to_string(sln_path)?;
        let source_dir = sln_path.parent()
            .map(|p| p.to_path_buf())
            .unwrap_or_else(|| PathBuf::from("."));

        let mut solution = Solution::with_source_directory(
            sln_path.file_stem()
                .and_then(|s| s.to_str())
                .unwrap_or("Unknown")
                .to_string(),
            source_dir.clone()
        );

        // 简化的.sln解析 - 查找项目引用
        for line in content.lines() {
            if line.starts_with("Project(") {
                if let Some(project_info) = self.parse_project_line(line) {
                    let project_path = source_dir.join(&project_info.path);

                    if project_path.exists() {
                        match self.parse_project(&project_path) {
                            Ok(project) => solution.projects.push(project),
                            Err(e) => {
                                log::warn!("Failed to parse project {}: {}", project_path.display(), e);
                            }
                        }
                    }
                }
            }
        }

        Ok(solution)
    }

    fn parse_project_line(&self, line: &str) -> Option<ProjectInfo> {
        // 解析格式: Project("{GUID}") = "ProjectName", "ProjectPath", "{ProjectGUID}"
        let parts: Vec<&str> = line.split(", ").collect();
        if parts.len() >= 2 {
            let path = parts[1].trim_matches('"');
            
            Some(ProjectInfo {
                path: path.to_string(),
            })
        } else {
            None
        }
    }

    fn parse_project(&self, vcxproj_path: &Path) -> Result<Project> {
        // 创建环境变量解析器
        let project_dir = vcxproj_path.parent().unwrap_or(Path::new(".")).to_path_buf();
        let mut env_resolver = if let Some(env_config) = &self.env_config {
            EnvironmentResolver::with_config(project_dir, env_config.clone())
        } else {
            EnvironmentResolver::new(project_dir)
        };
        let mut project_properties = HashMap::new();
        let file = File::open(vcxproj_path)?;
        let reader = BufReader::new(file);
        let parser = EventReader::new(reader);

        let project_name = vcxproj_path.file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("Unknown")
            .to_string();

        let mut project = Project::new(project_name, ProjectType::Executable);
        let mut current_config: Option<String> = None;
        let mut _current_platform: Option<String> = None;
        let mut in_item_group = false;
        let mut in_property_group = false;
        let mut in_item_definition_group = false;
        let mut in_clcompile = false;
        let mut in_link = false;
        let mut current_settings = BuildSettings::default();
        let mut current_element_name = String::new();
        let mut element_text = String::new();
        
        // 当前正在解析的源文件（用于处理 ExcludedFromBuild）
        let mut current_source_file: Option<usize> = None;
        
        // 用于收集项目级别的属性
        let mut _temp_qt_install = String::new();
        let mut _temp_platform_toolset = String::new();
        
        // 收集所有 Qt 文件，稍后添加到所有配置中
        let mut all_qt_moc_files: Vec<PathBuf> = Vec::new();
        let mut all_qt_ui_files: Vec<PathBuf> = Vec::new();
        let mut all_qt_resource_files: Vec<PathBuf> = Vec::new();
        
        // CustomBuild 解析相关变量
        let mut current_custom_build: Option<CustomBuildRule> = None;
        let mut in_custom_build = false;

        for event in parser {
            match event? {
                XmlEvent::StartElement { name, attributes, .. } => {
                    current_element_name = name.local_name.clone();
                    element_text.clear();
                    
                    match name.local_name.as_str() {
                        "ItemGroup" => in_item_group = true,
                        "PropertyGroup" => {
                            in_property_group = true;
                            // 检查是否是特定配置的属性组
                            for attr in &attributes {
                                if attr.name.local_name == "Condition" {
                                    if let Some((config, _platform)) = self.parse_condition(&attr.value) {
                                        current_config = Some(config);
                                        _current_platform = Some(_platform);
                                    }
                                }
                            }
                        }
                        "ItemDefinitionGroup" => {
                            in_item_definition_group = true;
                            // 检查是否是特定配置的定义组
                            for attr in &attributes {
                                if attr.name.local_name == "Condition" {
                                    info!("Found ItemDefinitionGroup condition: {}", attr.value);
                                    if let Some((config, _platform)) = self.parse_condition(&attr.value) {
                                        info!("Parsed ItemDefinitionGroup config: {} platform: {}", config, _platform);
                                        current_config = Some(config);
                                        _current_platform = Some(_platform);
                                    } else {
                                        info!("Failed to parse ItemDefinitionGroup condition: {}", attr.value);
                                    }
                                }
                            }
                        }
                        "ClCompile" if in_item_group => {
                            if let Some(include) = attributes.iter()
                                .find(|attr| attr.name.local_name == "Include") {
                                let source_path = vcxproj_path.parent()
                                    .unwrap_or(Path::new("."))
                                    .join(&include.value);
                                let source_file = SourceFile::new(source_path);
                                project.source_files.push(source_file);
                                current_source_file = Some(project.source_files.len() - 1);
                            }
                        }
                        "ClCompile" if in_item_definition_group => {
                            in_clcompile = true;
                        }
                        "Link" if in_item_definition_group => {
                            in_link = true;
                        }
                        // Qt 相关元素解析
                        "QtMoc" if in_item_group => {
                            if let Some(include) = attributes.iter()
                                .find(|attr| attr.name.local_name == "Include") {
                                let moc_path = vcxproj_path.parent()
                                    .unwrap_or(Path::new("."))
                                    .join(&include.value);
                                all_qt_moc_files.push(moc_path);
                            }
                        }
                        "QtUic" if in_item_group => {
                            if let Some(include) = attributes.iter()
                                .find(|attr| attr.name.local_name == "Include") {
                                let ui_path = vcxproj_path.parent()
                                    .unwrap_or(Path::new("."))
                                    .join(&include.value);
                                all_qt_ui_files.push(ui_path);
                            }
                        }
                        "QtRcc" if in_item_group => {
                            if let Some(include) = attributes.iter()
                                .find(|attr| attr.name.local_name == "Include") {
                                let rcc_path = vcxproj_path.parent()
                                    .unwrap_or(Path::new("."))
                                    .join(&include.value);
                                all_qt_resource_files.push(rcc_path);
                            }
                        }
                        "CustomBuild" if in_item_group => {
                            in_custom_build = true;
                            if let Some(include) = attributes.iter()
                                .find(|attr| attr.name.local_name == "Include") {
                                let source_path = vcxproj_path.parent()
                                    .unwrap_or(Path::new("."))
                                    .join(&include.value);
                                
                                // 检查是否是 MOC 文件（.h 文件）
                                let is_moc_file = include.value.ends_with(".h");
                                
                                current_custom_build = Some(CustomBuildRule {
                                    source_file: source_path,
                                    command: String::new(),
                                    outputs: Vec::new(),
                                    additional_inputs: Vec::new(),
                                    message: None,
                                    is_moc_file,
                                });
                            }
                        }
                        "Command" if in_custom_build => {
                            // 将在 EndElement 中处理
                        }
                        "Outputs" if in_custom_build => {
                            // 处理条件逻辑类似 Command
                        }
                        "AdditionalInputs" if in_custom_build => {
                            // 处理条件逻辑类似 Command
                        }
                        "Message" if in_custom_build => {
                            // 处理条件逻辑类似 Command
                        }
                        "ConfigurationType" if in_property_group => {
                            // 将在EndElement中处理
                        }
                        "PlatformToolset" if in_property_group => {
                            // 将在EndElement中处理
                        }
                        "CharacterSet" if in_property_group => {
                            // 将在EndElement中处理
                        }
                        "UseOfMfc" if in_property_group => {
                            // 将在EndElement中处理
                        }
                        "ExcludedFromBuild" if current_source_file.is_some() => {
                            // 在这里直接解析条件并保存，以便在 Characters 和 EndElement 中使用
                            let mut excluded_condition: Option<String> = None;
                            
                            for attr in &attributes {
                                if attr.name.local_name == "Condition" {
                                    if let Some((config, _platform)) = self.parse_condition(&attr.value) {
                                        excluded_condition = Some(config);
                                        break;
                                    }
                                }
                            }
                            
                            // 临时保存条件到 current_config，但这个值只对当前 ExcludedFromBuild 元素有效
                            current_config = excluded_condition;
                        }
                        "LanguageStandard" if in_property_group => {
                            // 将在EndElement中处理
                        }
                        "LanguageStandard" if in_clcompile => {
                            // 将在EndElement中处理
                        }
                        _ => {}
                    }
                }
                XmlEvent::EndElement { name } => {
                    match name.local_name.as_str() {
                        "ItemGroup" => {
                            in_item_group = false;
                            current_source_file = None; // 重置当前源文件索引
                            current_config = None; // 重置当前配置状态
                        }
                        "CustomBuild" => {
                            if let Some(custom_build) = current_custom_build.take() {
                                project.custom_build_rules.push(custom_build);
                            }
                            in_custom_build = false;
                        }
                        "Command" if in_custom_build => {
                            if let Some(ref mut custom_build) = current_custom_build {
                                // 如果命令为空，则使用当前解析的内容
                                if custom_build.command.is_empty() && !element_text.trim().is_empty() {
                                    let resolved_command = env_resolver.resolve_variables(&element_text, &BuildConfiguration::Debug);
                                    custom_build.command = resolved_command;
                                }
                            }
                        }
                        "Outputs" if in_custom_build => {
                            if let Some(ref mut custom_build) = current_custom_build {
                                // 如果输出为空，则使用当前解析的内容
                                if custom_build.outputs.is_empty() && !element_text.trim().is_empty() {
                                    let resolved_outputs = env_resolver.resolve_variables(&element_text, &BuildConfiguration::Debug);
                                    // 输出通常是单个文件路径
                                    custom_build.outputs.push(PathBuf::from(resolved_outputs));
                                }
                            }
                        }
                        "AdditionalInputs" if in_custom_build => {
                            if let Some(ref mut custom_build) = current_custom_build {
                                // 如果额外输入为空，则使用当前解析的内容
                                if custom_build.additional_inputs.is_empty() && !element_text.trim().is_empty() {
                                    let resolved_inputs = env_resolver.resolve_variables(&element_text, &BuildConfiguration::Debug);
                                    // AdditionalInputs 可能包含多个分号分隔的项
                                    let inputs: Vec<String> = resolved_inputs
                                        .split(';')
                                        .map(|s| s.trim().to_string())
                                        .filter(|s| !s.is_empty())
                                        .collect();
                                    custom_build.additional_inputs.extend(inputs);
                                }
                            }
                        }
                        "Message" if in_custom_build => {
                            if let Some(ref mut custom_build) = current_custom_build {
                                // 如果消息为空，则使用当前解析的内容
                                if custom_build.message.is_none() && !element_text.trim().is_empty() {
                                    custom_build.message = Some(element_text.trim().to_string());
                                }
                            }
                        }
                        // 处理元素内容在组结束之前
                        "QtInstall" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.enabled = true;
                                // 解析 QtInstall 格式: "5.12.5_x64" -> 版本 "5.12.5"
                                if let Some(version) = self.parse_qt_install(&element_text) {
                                    current_settings.qt_settings.version = Some(version);
                                }
                                // 保存 QtInstall 信息用于环境变量解析
                                _temp_qt_install = element_text.trim().to_string();
                                project_properties.insert("QtInstall".to_string(), _temp_qt_install.clone());
                            }
                        }
                        "QtModules" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.enabled = true;
                                // 解析 Qt 模块，通常以分号分隔
                                let modules: Vec<String> = element_text
                                    .split(';')
                                    .map(|s| s.trim().to_string())
                                    .filter(|s| !s.is_empty())
                                    .collect();
                                current_settings.qt_settings.modules.extend(modules);
                            }
                        }
                        "QtBuildConfig" if in_property_group => {
                            // 这个字段暂时记录，但主要依赖 Visual Studio 的构建配置
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.enabled = true;
                            }
                        }
                        "QtMocExe" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.tools.moc_exe = Some(PathBuf::from(element_text.trim()));
                            }
                        }
                        "QtUicExe" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.tools.uic_exe = Some(PathBuf::from(element_text.trim()));
                            }
                        }
                        "QtRccExe" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.qt_settings.tools.rcc_exe = Some(PathBuf::from(element_text.trim()));
                            }
                        }
                        "ConfigurationType" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.configuration_type = Some(element_text.trim().to_string());
                            }
                        }
                        "PlatformToolset" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.platform_toolset = Some(element_text.trim().to_string());
                                _temp_platform_toolset = element_text.trim().to_string();
                            }
                        }
                        "CharacterSet" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.character_set = Some(element_text.trim().to_string());
                            }
                        }
                        "UseOfMfc" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.use_of_mfc = Some(element_text.trim().to_string());
                            }
                        }
                        "ExcludedFromBuild" if current_source_file.is_some() => {
                            if !element_text.trim().is_empty() {
                                let excluded = element_text.trim().to_lowercase() == "true";
                                if let Some(index) = current_source_file {
                                    if let Some(config) = &current_config {
                                        let build_config = match config.as_str() {
                                            "Debug" => BuildConfiguration::Debug,
                                            "Release" => BuildConfiguration::Release,
                                            other => BuildConfiguration::Custom(other.to_string()),
                                        };
                                        if let Some(source_file) = project.source_files.get_mut(index) {
                                            log::debug!("Setting exclusion for file '{}' in config '{}' to '{}'", 
                                                source_file.path.display(), config, excluded);
                                            source_file.set_excluded_in_config(build_config, excluded);
                                        }
                                    }
                                }
                            }
                            // 立即重置配置状态，为下一个 ExcludedFromBuild 条件做准备
                            current_config = None;
                        }
                        "LanguageStandard" if in_property_group => {
                            if !element_text.trim().is_empty() {
                                current_settings.language_standard = Some(self.parse_language_standard(&element_text));
                                info!("Property group - language_standard:{}",&current_settings.language_standard.clone().unwrap());
                            }
                        }
                        "LanguageStandard" if in_clcompile => {
                            if !element_text.trim().is_empty() {
                                current_settings.language_standard = Some(self.parse_language_standard(&element_text));
                                info!("ClCompile - language_standard:{}",&current_settings.language_standard.clone().unwrap());
                            }
                        }
                        "AdditionalIncludeDirectories" if in_clcompile => {
                            if !element_text.trim().is_empty() {
                                // 使用环境变量解析器处理路径
                                let config = current_config.as_ref()
                                    .map(|c| match c.as_str() {
                                        "Debug" => BuildConfiguration::Debug,
                                        "Release" => BuildConfiguration::Release,
                                        other => BuildConfiguration::Custom(other.to_string()),
                                    })
                                    .unwrap_or(BuildConfiguration::Debug);
                                let dirs = env_resolver.resolve_path_list(&element_text, &config);
                                current_settings.include_directories.extend(dirs);
                            }
                        }
                        "PreprocessorDefinitions" if in_clcompile => {
                            if !element_text.trim().is_empty() {
                                let config = current_config.as_ref()
                                    .map(|c| match c.as_str() {
                                        "Debug" => BuildConfiguration::Debug,
                                        "Release" => BuildConfiguration::Release,
                                        other => BuildConfiguration::Custom(other.to_string()),
                                    })
                                    .unwrap_or(BuildConfiguration::Debug);
                                let defs: Vec<String> = element_text
                                    .split(';')
                                    .map(|s| s.trim())
                                    .filter(|s| !s.is_empty() && !s.starts_with('%'))
                                    .map(|s| env_resolver.resolve_variables(s, &config))
                                    .collect();
                                current_settings.preprocessor_definitions.extend(defs);
                            }
                        }
                        "AdditionalOptions" if in_clcompile => {
                            if !element_text.trim().is_empty() {
                                let config = current_config.as_ref()
                                    .map(|c| match c.as_str() {
                                        "Debug" => BuildConfiguration::Debug,
                                        "Release" => BuildConfiguration::Release,
                                        other => BuildConfiguration::Custom(other.to_string()),
                                    })
                                    .unwrap_or(BuildConfiguration::Debug);
                                let options: Vec<String> = element_text
                                    .split_whitespace()
                                    .map(|s| env_resolver.resolve_variables(s, &config))
                                    .filter(|s| !s.starts_with('%'))
                                    .collect();
                                current_settings.compiler_flags.extend(options);
                            }
                        }
                        "AdditionalLibraryDirectories" if in_link => {
                            if !element_text.trim().is_empty() {
                                let config = current_config.as_ref()
                                    .map(|c| match c.as_str() {
                                        "Debug" => BuildConfiguration::Debug,
                                        "Release" => BuildConfiguration::Release,
                                        other => BuildConfiguration::Custom(other.to_string()),
                                    })
                                    .unwrap_or(BuildConfiguration::Debug);
                                let dirs = env_resolver.resolve_path_list(&element_text, &config);
                                current_settings.library_directories.extend(dirs);
                            }
                        }
                        "AdditionalDependencies" if in_link => {
                            if !element_text.trim().is_empty() {
                                let config = current_config.as_ref()
                                    .map(|c| match c.as_str() {
                                        "Debug" => BuildConfiguration::Debug,
                                        "Release" => BuildConfiguration::Release,
                                        other => BuildConfiguration::Custom(other.to_string()),
                                    })
                                    .unwrap_or(BuildConfiguration::Debug);
                                let libs: Vec<String> = element_text
                                    .split(';')
                                    .map(|s| s.trim())
                                    .filter(|s| !s.is_empty() && !s.starts_with('%'))
                                    .map(|s| env_resolver.resolve_variables(s, &config))
                                    .collect();
                                current_settings.libraries.extend(libs);
                            }
                        }
                        "PropertyGroup" => {
                            if in_property_group && current_config.is_some() {
                                let config = match current_config.as_ref().unwrap().as_str() {
                                    "Debug" => BuildConfiguration::Debug,
                                    "Release" => BuildConfiguration::Release,
                                    other => BuildConfiguration::Custom(other.to_string()),
                                };
                                info!("Saving PropertyGroup config {:?} with language_standard: {:?}", config, current_settings.language_standard);
                                
                                // 合并到已有配置，而不是覆盖（PropertyGroup也可能需要合并）
                                if let Some(existing_settings) = project.configurations.get_mut(&config) {
                                    // 合并设置：只更新非空/非默认的字段
                                    if current_settings.language_standard.is_some() {
                                        existing_settings.language_standard = current_settings.language_standard.clone();
                                    }
                                    if !current_settings.preprocessor_definitions.is_empty() {
                                        existing_settings.preprocessor_definitions.extend(current_settings.preprocessor_definitions.clone());
                                    }
                                    if !current_settings.include_directories.is_empty() {
                                        existing_settings.include_directories.extend(current_settings.include_directories.clone());
                                    }
                                    if !current_settings.library_directories.is_empty() {
                                        existing_settings.library_directories.extend(current_settings.library_directories.clone());
                                    }
                                    if !current_settings.libraries.is_empty() {
                                        existing_settings.libraries.extend(current_settings.libraries.clone());
                                    }
                                    if !current_settings.compiler_flags.is_empty() {
                                        existing_settings.compiler_flags.extend(current_settings.compiler_flags.clone());
                                    }
                                    if !current_settings.linker_flags.is_empty() {
                                        existing_settings.linker_flags.extend(current_settings.linker_flags.clone());
                                    }
                                    if current_settings.qt_settings.enabled {
                                        existing_settings.qt_settings = current_settings.qt_settings.clone();
                                    }
                                    // 合并新的属性
                                    if current_settings.configuration_type.is_some() {
                                        existing_settings.configuration_type = current_settings.configuration_type.clone();
                                    }
                                    if current_settings.platform_toolset.is_some() {
                                        existing_settings.platform_toolset = current_settings.platform_toolset.clone();
                                    }
                                    if current_settings.character_set.is_some() {
                                        existing_settings.character_set = current_settings.character_set.clone();
                                    }
                                    if current_settings.use_of_mfc.is_some() {
                                        existing_settings.use_of_mfc = current_settings.use_of_mfc.clone();
                                    }
                                } else {
                                    // 配置还不存在，直接插入
                                    project.configurations.insert(config, current_settings.clone());
                                }
                                
                                current_settings = BuildSettings::default();
                                current_config = None;
                                _current_platform = None;
                            }
                            in_property_group = false;
                        }
                        "ItemDefinitionGroup" => {
                            if in_item_definition_group && current_config.is_some() {
                                let config = match current_config.as_ref().unwrap().as_str() {
                                    "Debug" => BuildConfiguration::Debug,
                                    "Release" => BuildConfiguration::Release,
                                    other => BuildConfiguration::Custom(other.to_string()),
                                };
                                info!("Saving ItemDefinitionGroup config {:?} with language_standard: {:?}", config, current_settings.language_standard);
                                
                                // 合并到已有配置，而不是覆盖
                                if let Some(existing_settings) = project.configurations.get_mut(&config) {
                                    // 合并设置：只更新非空/非默认的字段
                                    if current_settings.language_standard.is_some() {
                                        existing_settings.language_standard = current_settings.language_standard.clone();
                                    }
                                    if !current_settings.preprocessor_definitions.is_empty() {
                                        existing_settings.preprocessor_definitions.extend(current_settings.preprocessor_definitions.clone());
                                    }
                                    if !current_settings.include_directories.is_empty() {
                                        existing_settings.include_directories.extend(current_settings.include_directories.clone());
                                    }
                                    if !current_settings.library_directories.is_empty() {
                                        existing_settings.library_directories.extend(current_settings.library_directories.clone());
                                    }
                                    if !current_settings.libraries.is_empty() {
                                        existing_settings.libraries.extend(current_settings.libraries.clone());
                                    }
                                    if !current_settings.compiler_flags.is_empty() {
                                        existing_settings.compiler_flags.extend(current_settings.compiler_flags.clone());
                                    }
                                    if !current_settings.linker_flags.is_empty() {
                                        existing_settings.linker_flags.extend(current_settings.linker_flags.clone());
                                    }
                                    if current_settings.qt_settings.enabled {
                                        existing_settings.qt_settings = current_settings.qt_settings.clone();
                                    }
                                    // 合并新的属性
                                    if current_settings.configuration_type.is_some() {
                                        existing_settings.configuration_type = current_settings.configuration_type.clone();
                                    }
                                    if current_settings.platform_toolset.is_some() {
                                        existing_settings.platform_toolset = current_settings.platform_toolset.clone();
                                    }
                                    if current_settings.character_set.is_some() {
                                        existing_settings.character_set = current_settings.character_set.clone();
                                    }
                                    if current_settings.use_of_mfc.is_some() {
                                        existing_settings.use_of_mfc = current_settings.use_of_mfc.clone();
                                    }
                                } else {
                                    // 配置还不存在，直接插入（这种情况发生在 ItemDefinitionGroup 在 PropertyGroup 之前）
                                    project.configurations.insert(config, current_settings.clone());
                                }
                                
                                current_settings = BuildSettings::default();
                                current_config = None;
                                _current_platform = None;
                            }
                            in_item_definition_group = false;
                        }
                        "ClCompile" if in_item_definition_group => {
                            in_clcompile = false;
                        }
                        "Link" if in_item_definition_group => {
                            in_link = false;
                        }
                        _ => {}
                    }
                    current_element_name.clear();
                    element_text.clear();
                }
                XmlEvent::Characters(text) => {
                    if (in_property_group || in_clcompile || in_link || in_custom_build || in_item_group) && !current_element_name.is_empty() {
                        element_text.push_str(&text);
                    }
                }
                _ => {}
            }
        }

        // 更新环境解析器的属性
        if !project_properties.is_empty() {
            env_resolver.update_from_project_properties(&project_properties);
        }

        // 如果没有找到配置，添加默认配置
        if project.configurations.is_empty() {
            project.configurations.insert(BuildConfiguration::Debug, BuildSettings::default());
            project.configurations.insert(BuildConfiguration::Release, BuildSettings::default());
        }

        // 如果检测到 Qt 文件，标记所有配置为 Qt 项目
        let has_qt_files = !all_qt_moc_files.is_empty() || !all_qt_ui_files.is_empty() || !all_qt_resource_files.is_empty();
        
        // 处理 CustomBuild 中的 MOC 文件
        let custom_moc_files: Vec<CustomBuildRule> = project.custom_build_rules.iter()
            .filter(|rule| rule.is_moc_file && rule.command.contains("moc.exe"))
            .cloned()
            .collect();
        
        let has_custom_moc_files = !custom_moc_files.is_empty();
        
        if has_qt_files || has_custom_moc_files {
            // 为所有配置启用 Qt 并添加默认模块
            for (_, settings) in &mut project.configurations {
                if !settings.qt_settings.enabled {
                    settings.qt_settings.enabled = true;
                    // 如果没有指定模块，添加默认的基础模块
                    if settings.qt_settings.modules.is_empty() {
                        settings.qt_settings.modules.extend(vec![
                            "core".to_string(),
                            "gui".to_string(),
                            "widgets".to_string()
                        ]);
                    }
                }
                // 添加 Qt 文件
                settings.qt_settings.moc_files.extend(all_qt_moc_files.clone());
                settings.qt_settings.ui_files.extend(all_qt_ui_files.clone());
                settings.qt_settings.resource_files.extend(all_qt_resource_files.clone());
                
                // 添加来自 CustomBuild 的 MOC 文件
                settings.qt_settings.custom_moc_files.extend(custom_moc_files.clone());
            }
        }

        Ok(project)
    }

    fn parse_condition(&self, condition: &str) -> Option<(String, String)> {
        // 解析条件，支持两种格式:
        // 1. "'$(Configuration)|$(Platform)' == 'Debug|x64'" (带空格)
        // 2. "'$(Configuration)|$(Platform)'=='Debug|Win32'" (不带空格)
        let start_pos = if let Some(pos) = condition.find(" == ") {
            pos + 4
        } else if let Some(pos) = condition.find("==") {
            pos + 2
        } else {
            return None;
        };
        
        let value_part = &condition[start_pos..];
        let cleaned = value_part.trim().trim_matches('\'').trim_matches('"');
        if let Some(pipe_pos) = cleaned.find('|') {
            let config = cleaned[..pipe_pos].trim().to_string();
            let platform = cleaned[pipe_pos + 1..].trim().to_string();
            return Some((config, platform));
        }
        None
    }


    pub fn parse_qt_install(&self, qt_install: &str) -> Option<String> {
        // 解析 QtInstall 格式: "5.12.5_x64" -> "5.12.5"
        //                   "6.2.0_msvc2019_64" -> "6.2.0"
        let trimmed = qt_install.trim();
        
        // 查找下划线前的版本号部分
        if let Some(underscore_pos) = trimmed.find('_') {
            let version_part = &trimmed[..underscore_pos];
            // 验证是否为有效的版本号格式
            let version_regex = regex::Regex::new(r"^\d+\.\d+(\.\d+)?$").ok()?;
            if version_regex.is_match(version_part) {
                return Some(version_part.to_string());
            }
        }
        
        // 如果没有下划线，检查整个字符串是否为版本号
        let version_regex = regex::Regex::new(r"^\d+\.\d+(\.\d+)?$").ok()?;
        if version_regex.is_match(trimmed) {
            return Some(trimmed.to_string());
        }
        
        None
    }

    fn parse_language_standard(&self, standard: &str) -> String {
        let trimmed = standard.trim();
        match trimmed {
            "stdcpp98" => "c++98".to_string(),
            "stdcpp03" => "c++03".to_string(),
            "stdcpp11" => "c++11".to_string(),
            "stdcpp14" => "c++14".to_string(),
            "stdcpp17" => "c++17".to_string(),
            "stdcpp20" => "c++20".to_string(),
            "stdcpp23" => "c++23".to_string(),
            "stdcpplatest" => "c++23".to_string(), // 最新标准
            "" | "Default" => "c++17".to_string(), // 默认标准
            _ => "c++17".to_string(), // 无法识别时的默认值
        }
    }
}

struct ProjectInfo {
    path: String,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_condition() {
        let parser = VsParser::new();
        let condition = "'$(Configuration)|$(Platform)'=='Debug|Win32'";
        let result = parser.parse_condition(condition);
        assert_eq!(result, Some(("Debug".to_string(), "Win32".to_string())));
    }

    #[test]
    fn test_parse_project_line() {
        let parser = VsParser::new();
        let line = r#"Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProject", "TestProject\TestProject.vcxproj", "{12345678-1234-1234-1234-123456789012}""#;
        let result = parser.parse_project_line(line);
        assert!(result.is_some());
        let info = result.unwrap();
        assert_eq!(info.path, r"TestProject\TestProject.vcxproj");
    }

    #[test]
    fn test_parse_qt_install() {
        let parser = VsParser::new();
        
        // 测试标准格式
        assert_eq!(parser.parse_qt_install("5.12.5_x64"), Some("5.12.5".to_string()));
        assert_eq!(parser.parse_qt_install("6.2.0_msvc2019_64"), Some("6.2.0".to_string()));
        
        // 测试只有版本号的情况
        assert_eq!(parser.parse_qt_install("5.15.2"), Some("5.15.2".to_string()));
        
        // 测试无效格式
        assert_eq!(parser.parse_qt_install("invalid_format"), None);
        assert_eq!(parser.parse_qt_install(""), None);
    }

    #[test]
    fn test_parse_language_standard() {
        let parser = VsParser::new();
        
        // 测试标准的 Visual Studio C++ 标准值
        assert_eq!(parser.parse_language_standard("stdcpp98"), "c++98");
        assert_eq!(parser.parse_language_standard("stdcpp03"), "c++03");
        assert_eq!(parser.parse_language_standard("stdcpp11"), "c++11");
        assert_eq!(parser.parse_language_standard("stdcpp14"), "c++14");
        assert_eq!(parser.parse_language_standard("stdcpp17"), "c++17");
        assert_eq!(parser.parse_language_standard("stdcpp20"), "c++20");
        assert_eq!(parser.parse_language_standard("stdcpp23"), "c++23");
        
        // 测试特殊值
        assert_eq!(parser.parse_language_standard("stdcpplatest"), "c++23");
        assert_eq!(parser.parse_language_standard("Default"), "c++17");
        assert_eq!(parser.parse_language_standard(""), "c++17");
        
        // 测试带空格的情况
        assert_eq!(parser.parse_language_standard("  stdcpp17  "), "c++17");
        
        // 测试未知值
        assert_eq!(parser.parse_language_standard("unknown"), "c++17");
        assert_eq!(parser.parse_language_standard("invalidstd"), "c++17");
    }

    #[test]
    fn test_parse_item_definition_group_language_standard() {
        let parser = VsParser::new();
        
        // 创建一个包含 ItemDefinitionGroup 的测试项目文件
        let test_vcxproj = r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <LanguageStandard>stdcpp17</LanguageStandard>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
  </ItemGroup>
</Project>"#;
        
        use tempfile::NamedTempFile;
        use std::io::Write;
        
        let mut temp_file = NamedTempFile::new().unwrap();
        temp_file.write_all(test_vcxproj.as_bytes()).unwrap();
        temp_file.flush().unwrap();
        
        let result = parser.parse_project(temp_file.path());
        assert!(result.is_ok(), "Should parse project successfully");
        
        let project = result.unwrap();
        
        // 检查是否正确解析了 Release 配置中的语言标准
        if let Some(settings) = project.configurations.get(&crate::core::BuildConfiguration::Release) {
            assert_eq!(settings.language_standard, Some("c++17".to_string()));
        } else {
            panic!("Release configuration not found");
        }
    }

    #[test]
    fn test_parse_custom_build_moc() {
        use tempfile::tempdir;
        
        let temp_dir = tempdir().unwrap();
        let project_dir = temp_dir.path();
        let vcxproj_path = project_dir.join("test_custom_moc.vcxproj");
        
        // 创建包含 CustomBuild MOC 的测试项目文件
//         let vcxproj_content = r#"<?xml version="1.0" encoding="utf-8"?>
// <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
//   <ItemGroup>
//     <CustomBuild Include="..\src\ClearThread\clearthread.h">
//       <AdditionalInputs>$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
//       <Message>Moc'ing clearthread.h...</Message>
//       <Outputs>.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
//       <Command>"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_SQL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB</Command>
//     </CustomBuild>
//   </ItemGroup>
//   <ItemGroup>
//     <ClCompile Include="main.cpp" />
//   </ItemGroup>
// </Project>"#;

        let vcxproj_content = r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <CustomBuild Include="..\src\ClearThread\clearthread.h">
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing clearthread.h...</Message>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DMEMORY_DLL_USE -DLOG_DLL_USE -DSA_UNICODE -DUNICODE -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_SQL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D%(PreprocessorDefinitions)  "-ID:\project\rf\rf_guide\software\trunk\applications\laser_cut_guide\project\isv_temp_match\include" "-I.\..\..\..\..\collimator\trunk\1.0\include" "-I.\..\..\..\..\20180122-IRB\dist\1.1.1-alpha.1\include" "-I.\..\..\..\..\..\Common\PCL\PCL 1.8.0_VS2013_x64\3rdParty\Eigen\eigen3" "-I.\..\..\..\..\..\Common\SQLAPI\sqlapi-4.1.6(Win)\SQLAPI\include" "-I.\..\..\..\..\..\Common\log4cplus\log4cplus-1.2.0\include" "-I.\..\include" "-I.\..\..\..\..\20170214-modules\include" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtSql" "-I$(QTDIR)\include\QtWidgets" "-I.\..\src\QUDPComm" "-I.\..\src\TreeDelegate" "-I.\..\src\ImageFrame" "-I.\..\src\Sensor" "-I.\..\src\Algorithm" "-I.\..\src\Setting" "-I.\..\src\Json" "-I.\..\src\Signal" "-I.\..\src\CommThread" "-I.\..\src\Robot" "-I.\..\src" "-I.\..\src\ClearThread" "-I$(QTDIR)\include\QtXml" "-I$(AllIncludePaths)" "-I$(NOINHERIT)"</Command>
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
      <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing clearthread.h...</Message>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DSA_UNICODE -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_SQL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D%(PreprocessorDefinitions)  "-I$(AllIncludePaths)" "-I.\GeneratedFiles" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtSql" "-I$(QTDIR)\include\QtWidgets" "-I.\..\src\QUDPComm" "-I.\..\src\TreeDelegate" "-I.\..\src\ImageFrame" "-I.\..\src\Sensor" "-I.\..\src\Algorithm" "-I.\..\src\Setting" "-I.\..\src\Json" "-I.\..\src\Signal" "-I.\..\src\CommThread" "-I.\..\src\ClearThread" "-I$(QTDIR)\include\QtXml" "-I.\..\src\Robot" "-I.\..\src"</Command>
    </CustomBuild>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
  </ItemGroup>
</Project>"#;
        std::fs::write(&vcxproj_path, vcxproj_content).unwrap();
        
        let parser = VsParser::new();
        let project = parser.parse_project(&vcxproj_path).unwrap();
        
        // 验证 CustomBuild 规则被正确解析
        assert_eq!(project.custom_build_rules.len(), 1);
        
        let custom_build = &project.custom_build_rules[0];
        
        assert!(custom_build.is_moc_file);
        assert!(custom_build.source_file.to_string_lossy().contains("clearthread.h"));
        assert!(custom_build.command.contains("moc.exe"));
        assert!(!custom_build.outputs.is_empty());
        assert!(custom_build.outputs[0].to_string_lossy().contains("moc_"));
        assert!(!custom_build.additional_inputs.is_empty());
        assert!(custom_build.message.is_some());
        
        // 验证项目被标记为 Qt 项目
        assert!(!project.configurations.is_empty());
        for (_, settings) in &project.configurations {
            assert!(settings.qt_settings.enabled);
            assert!(!settings.qt_settings.custom_moc_files.is_empty());
        }
    }

    #[test]
    fn test_parse_excluded_from_build() {
        use tempfile::tempdir;
        
        let temp_dir = tempdir().unwrap();
        let project_dir = temp_dir.path();
        let vcxproj_path = project_dir.join("test_excluded.vcxproj");
        
        // 创建包含 ExcludedFromBuild 的测试项目文件
        let vcxproj_content = r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="main.cpp" />
    <ClCompile Include="GeneratedFiles\Debug\moc_test.cpp">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="GeneratedFiles\Release\moc_test.cpp">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
    </ClCompile>
  </ItemGroup>
</Project>"#;
        std::fs::write(&vcxproj_path, vcxproj_content).unwrap();
        
        let parser = VsParser::new();
        let project = parser.parse_project(&vcxproj_path).unwrap();
        
        // 验证源文件被正确解析
        assert_eq!(project.source_files.len(), 3);
        
        // 验证第一个文件没有被排除
        let main_cpp = project.source_files.iter()
            .find(|f| f.path.to_string_lossy().contains("main.cpp"))
            .unwrap();
        assert!(!main_cpp.is_excluded_in_config(&BuildConfiguration::Debug));
        assert!(!main_cpp.is_excluded_in_config(&BuildConfiguration::Release));
        
        // 验证 Debug moc 文件在 Release 配置中被排除
        let debug_moc = project.source_files.iter()
            .find(|f| f.path.to_string_lossy().contains("GeneratedFiles") && 
                       f.path.to_string_lossy().contains("Debug") &&
                       f.path.to_string_lossy().contains("moc_test.cpp"))
            .unwrap();
        assert!(!debug_moc.is_excluded_in_config(&BuildConfiguration::Debug));
        assert!(debug_moc.is_excluded_in_config(&BuildConfiguration::Release));
        
        // 验证 Release moc 文件在 Debug 配置中被排除
        let release_moc = project.source_files.iter()
            .find(|f| f.path.to_string_lossy().contains("GeneratedFiles") && 
                       f.path.to_string_lossy().contains("Release") &&
                       f.path.to_string_lossy().contains("moc_test.cpp"))
            .unwrap();
        assert!(release_moc.is_excluded_in_config(&BuildConfiguration::Debug));
        assert!(!release_moc.is_excluded_in_config(&BuildConfiguration::Release));
    }

    #[test]
    fn test_parse_property_group_attributes() {
        use tempfile::tempdir;
        
        let temp_dir = tempdir().unwrap();
        let project_dir = temp_dir.path();
        let vcxproj_path = project_dir.join("test_properties.vcxproj");
        
        // 创建包含 PropertyGroup 属性的测试项目文件
        let vcxproj_content = r#"<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <PlatformToolset>v141</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
    <UseOfMfc>Dynamic</UseOfMfc>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <PlatformToolset>v120</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>false</UseOfMfc>
  </PropertyGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
  </ItemGroup>
</Project>"#;
        std::fs::write(&vcxproj_path, vcxproj_content).unwrap();
        
        let parser = VsParser::new();
        let project = parser.parse_project(&vcxproj_path).unwrap();
        
        // 验证 Debug 配置的属性
        if let Some(debug_settings) = project.configurations.get(&BuildConfiguration::Debug) {
            assert_eq!(debug_settings.configuration_type, Some("Application".to_string()));
            assert_eq!(debug_settings.platform_toolset, Some("v141".to_string()));
            assert_eq!(debug_settings.character_set, Some("Unicode".to_string()));
            assert_eq!(debug_settings.use_of_mfc, Some("Dynamic".to_string()));
        } else {
            panic!("Debug configuration not found");
        }
        
        // 验证 Release 配置的属性
        if let Some(release_settings) = project.configurations.get(&BuildConfiguration::Release) {
            assert_eq!(release_settings.configuration_type, Some("Application".to_string()));
            assert_eq!(release_settings.platform_toolset, Some("v120".to_string()));
            assert_eq!(release_settings.character_set, Some("MultiByte".to_string()));
            assert_eq!(release_settings.use_of_mfc, Some("false".to_string()));
        } else {
            panic!("Release configuration not found");
        }
    }

    #[test]
    fn test_normalize_path_unc_prefix() {
        let unc = Path::new(r"\\?\UNC\server\share\project.sln");
        let normalized = VsParser::normalize_path(unc);
        assert_eq!(normalized.to_string_lossy(), r"\\server\share\project.sln");

        let drive = Path::new(r"\\?\D:\\work\\project.sln");
        let normalized_drive = VsParser::normalize_path(drive);
        assert_eq!(normalized_drive.to_string_lossy(), r"D:\\work\\project.sln");
    }
}
